import time
import bcrypt
from ..main import app, db, logger
from ..models import User, Booking, UserWithoutPassword, NewBookingData
from ..exceptions import BookingNotFound, UserNotFound
from typing import Union
import json
from fastapi import HTTPException
import uuid

path = '/api/bookings'


@app.get(path + "/get_bookings", tags=['bookings'])
async def get_bookings_api():
    try:
        bookings = await db.get_bookings()
    except Exception:
        logger.error("Error while execute get_users db_method")
        raise HTTPException(status_code=500, detail="Internal error.")
    return bookings


@app.get(path + "/get_booking/{user_id}", tags=['bookings'])
async def get_booking_api(booking_id: str):
    try:
        booking_id = uuid.UUID(booking_id)
        booking = await db.get_booking(booking_id)
    except ValueError:
        raise HTTPException(status_code=400, detail="booking_id must be uuid string")
    except BookingNotFound:
        raise HTTPException(status_code=404, detail="booking with that id not found")
    except Exception as ex:
        logger.error(f"Error while execute get_booking db_method (bid: {booking_id}, errmsg: {ex})", exc_info=True)
        raise HTTPException(status_code=500, detail="unexpected error")
    return booking


@app.post(path + '/add_booking', tags=['bookings'])
async def add_booking_api(new_booking_data: NewBookingData):
    try:
        user = await db.get_user(new_booking_data.user_id)
    except UserNotFound:
        raise HTTPException(status_code=404, detail="user with that id not found")
    except Exception as ex:
        logger.error(f"Error while execute get_booking db_method (data: {new_booking_data}, errmsg: {ex})", exc_info=True)
        raise HTTPException(status_code=500, detail="unexpected error")
    if new_booking_data.start_time > new_booking_data.end_time:
        raise HTTPException(status_code=422, detail="start time must be lower then end time")
    data = {
        "booking_id": uuid.uuid4(),
        "user_id": user.id,
        "start_time": new_booking_data.start_time,
        "end_time": new_booking_data.end_time,
        "comment": new_booking_data.comment,
        "created_at": time.time() if new_booking_data.created_at is None else new_booking_data.created_at,
    }
    booking = Booking(**data)
    await db.add_booking(booking)
    return booking


@app.get(path + '/del_booking/{booking_id}', tags=['bookings'])
async def get_user_api(booking_id: str):
    try:
        booking_id = uuid.UUID(booking_id)
        booking = await db.get_booking(booking_id)
        await db.del_booking(booking_id)
    except ValueError:
        raise HTTPException(status_code=400, detail="booking_id must be uuid string")
    except BookingNotFound:
        raise HTTPException(status_code=404, detail="booking with that id not found")
    except Exception as ex:
        logger.error(f"Error while execute del_booking db_method (bid: {booking_id}, errmsg: {ex})", exc_info=True)
        raise HTTPException(status_code=500, detail="unexpected error")
    return "success"
